//
//  MemoryModel.cpp
//  sad
//
//  Created by Christopher Kemsley on 1/27/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#include "MemoryInterface.hpp"
#include "SystemCDefinitions.hpp"

#include "Settings.hpp"
#include "Codec.hpp"
#include "ModuleFactory.hpp"
#include "PubSub.hpp"

#include <string>
#include <stdio.h>


#define MEM_SIZE	65535	// Default size. Overridden by config file if specified





struct	MemoryLine
{
	unsigned	unsignedValue ;
	
	MemoryLine ()	:	unsignedValue(0) { }
	~MemoryLine () { }
} ;




struct	MemoryFileSettings : public Settings
{
	std::string		interfaceName ;
	URL				url ;
	unsigned		size ;
	
	
	MemoryFileSettings ( std::string const & name )
	:	Settings(name)
	,	interfaceName	( "memory" )
	,	url				()
	,	size			( MEM_SIZE )
		{
		add ( "interfaceName" , interfaceName ) ;
		add ( "size" , size ) ;
		add ( "path" , url ) ;
		}
	
	virtual void validate ()
		{
		if ( size == 0 )
			Log::warning("MemoryFileSettings") << "File-Initialized Memory has 0-length size" ;
		}
} ;










class	FileInitializedMemory : public ConfiguredModel<MemoryFileSettings> , virtual public simple_mem_if
{
public:
	
	/** Structure **/
	
	MemoryLine*					mBuffer ;
	Publication<simple_mem_if>	mPublication ;
	
	
	
	/** Construction **/
	
	FileInitializedMemory ( ModelVariant const & name )
	:	ConfiguredModel<MemoryFileSettings> ( name )
		{
		// Initialize the data
		mBuffer = new MemoryLine [ mConfig.size ] ; // constructor zeros it
		_init_ascii () ;
		
		// Publish the interface
		mPublication = mConfig.interfaceName ;
		mPublication = this ; // templated already for simple_mem_if*
		}
	virtual ~FileInitializedMemory ()
		{
		delete [] mBuffer ;
		}
	
	
	
	
	/** File reading **/
	
	void	_init_ascii ()
		{
		FILE * file = fopen ( mConfig.url.absolutePath().c_str() , "r" ) ;
		
		if ( file != 0 )
			{
			unsigned remaining = mConfig.size ;
			MemoryLine * here = mBuffer ;
			while ( !feof(file) && 0!=remaining-- )
				{
				fscanf ( file , "%*[^1234567890]" ) ;
				MemoryLine & value = *(here++) ;
				fscanf ( file , "%u" , &value.unsignedValue ) ;
				}
			
			fclose ( file ) ;
			}
		}
	
	
	
	/** Memory Interface **/
	
    virtual bool	Write	( unsigned int addr , unsigned int  data )
		{
		Log::states("FileInitializedMemory") << "Writing: " << addr ;
		if ( addr >= mConfig.size )
			return false ;
		
		mBuffer[addr] . unsignedValue = data ;
		Log::states("FileInitializedMemory") << "Value: " << data ;
		
		return true ;
		}
    virtual bool	Read	( unsigned int addr , unsigned int& data )
		{
		Log::states("FileInitializedMemory") << "Reading: " << addr ;
		if ( addr >= mConfig.size )
			return false ;
		
		data = mBuffer[addr] . unsignedValue ;
		Log::states("FileInitializedMemory") << "Value: " << data ;
		
		return true ;
		}
	
} ;



TypedModuleMaker<FileInitializedMemory>	_FileInitializedMemory ( "Memory.file.untimed" ) ;

